package newx.com.loader
{
	import engine.data.ModelLocator;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.Security;
	import flash.system.SecurityDomain;
	import flash.system.System;
	import flash.utils.ByteArray;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;
	
	import newx.utils.debug.IO;
		
	/**
	 * swf文件加载，无只带进度条，适合加载文件大小较小的文件
	 * @author riki(王俊)	2009/9/23
	 */
	public class SwfLoader
	{
		//1级加载队列:
		static private var _itemArray1		:Array	=	[];
		
		//2级缓存加载队列:
		static private var _itemArray2		:Array	=	[];
		
		//加载器是否空闲
		static private var _isFree			:Boolean=	false;
		
		//缓存加载器
		static private var _swfLoaderArr		:Array;
		static private var model				:ModelLocator = ModelLocator.getInstance();
		//加载线程
		static private var _lines				:uint	=	5;
		
//		static private var _testCount			:uint	=	0;
		
		static public  var CDN				:String		=	"";
		
		static public  var isTest				:Boolean	=	false;
		
		/**自定义加载方法*/
		static private var _custLoadFunction	:Function	=	null;
		
		/**解密方法*/
		static private var _unEncryptByte		:Function	=	null;
		//**********************************************************
		
		//对象加载完成后将要添加的容器
		private	var		_beAddContainer		:DisplayObjectContainer;
		
		private	var		_complete			:Function;
		
		private	var		_valList			:Array;
		
		//***********************************************************
				
		private var		_isLoading			:Boolean	=	false;
		private var		loader				:Loader;
		private var		urlLoader			:URLLoader;
		private var		request				:URLRequest =	new URLRequest();
		
		/**自定义加载器*/
		private var		_cLoader			:Object;
		private var     	_url				:String		=	"";
		//***********************************************************
		
		
		
		public function SwfLoader()
		{
			super();	
		}
		
		/**初始化自定义加载，如果有*/
		public static function setCustLoad(custLoadFunction:Function):void
		{
			_custLoadFunction	=	custLoadFunction;
		}
		
		/**初始化自定义加载，如果有*/
		public static function setUnEncryptByte(fun:Function):void
		{
			_unEncryptByte	=	fun;
		}
		
		
		public static function testAllLoader():void
		{
			for(var i:int = 0;i< _swfLoaderArr.length;i++)
			{
				var load:SwfLoader = _swfLoaderArr[i];
				IO.traceError("swfloader"+ i +":" + load._isLoading,load._url);
			}
		}
		
		/**
		 * 加载资源 
		 * @param url				：资源地址
		 * @param canBeFind			：是否动过改变资源加载后的存放域，使得资源可以通过类名被重新创建（可选，默认false);
		 * @param beAddContainer	：显示容器（可选，当有值时，自动添加到容器中）
		 * @param complete			：完成处理函数
		 * @param valList			：跟随complete一起传递的参数
		 * 
		 */		
		public static function StartLoad(
			url				:String,
			beAddContainer	:DisplayObjectContainer = 	null,
			complete		:Function				=	null,
			valList			:Array					=	null):void
		{
			if(_swfLoaderArr == null)
			{
				_swfLoaderArr	=	new Array();	
				for(var i:int = 0 ; i < _lines ; i ++)
				{
					_swfLoaderArr.push(new SwfLoader());
				}
			}
			
//			IO.traceError("进入加载队列 " +　url,_isFree );
			
			//缓存加载队列	
			if(_isFree)
			{
				_itemArray1.push([url,beAddContainer,complete,valList]);
			}
			else
			{				
				_itemArray2.push([url,beAddContainer,complete,valList]);
			}
			//开始队列
			findFreeToLoad();
		}
		
		static public function CloseAll():void
		{
			var i	:uint	=	0;
			var len	:uint	=	0;
			//先从_itemArray1中找
			len	=	_itemArray1.length;
			for(i=0;	i<len;	i++)
			{
				_itemArray1.splice(i,1);//删除
				i--;//循环变量退后一个
				len--;//总数减少一个
			}
			//从_itemArray2中查找
			len	=	_itemArray2.length;
			for(i=0;	i<len;	i++)
			{
				_itemArray2.splice(i,1);//删除
				i--;//循环变量退后一个
				len--;//总数减少一个
			}
			//从_swfLoaderArr中查找
			len	=	_lines;
			for(i=0;	i<len;	i++)
			{
				if (SwfLoader(_swfLoaderArr[i])._isLoading)
				{
					try
					{
						if(SwfLoader(_swfLoaderArr[i])._cLoader != null)
						{
							SwfLoader(_swfLoaderArr[i])._cLoader.close();
						}
						
						if(SwfLoader(_swfLoaderArr[i]).loader != null)
						{
							SwfLoader(_swfLoaderArr[i]).closeAndRemoveLoader();
						}
					}
					catch(e:Error)
					{
						IO.traceError(e.errorID,e.message);
						IO.traceError(e.getStackTrace());
					}
					SwfLoader(_swfLoaderArr[i])._isLoading		=	false;
				}				
			}
		}
		
		static public function Close(url:String):void
		{
//			_itemArray1.push([url,beAddContainer,complete,valList]);
			var i	:uint	=	0;
			var len	:uint	=	0;
			//先从_itemArray1中找
			len	=	_itemArray1.length;
			for(i=0;	i<len;	i++)
			{
				if(_itemArray1[i][0]	==	url)
				{
					_itemArray1.splice(i,1);//删除
					i--;//循环变量退后一个
					len--;//总数减少一个
					IO.traceLog("SwfLoader关掉一个URL加载项(未开始)",url);
				}
			}
			//从_itemArray2中查找
			len	=	_itemArray2.length;
			for(i=0;	i<len;	i++)
			{
				if(_itemArray2[i][0]	==	url)
				{
					_itemArray2.splice(i,1);//删除
					i--;//循环变量退后一个
					len--;//总数减少一个
					IO.traceLog("SwfLoader关掉一个URL加载项(未开始)",url);
				}
			}
			//从_swfLoaderArr中查找
			len	=	_lines;
			for(i=0;	i<len;	i++)
			{
				if(_swfLoaderArr[i]._isLoading	&&
					_swfLoaderArr[i]._url	==	url)
				{
					try
					{
						if(SwfLoader(_swfLoaderArr[i])._cLoader != null)
						{
							SwfLoader(_swfLoaderArr[i])._cLoader.close();
						}
						
						if(SwfLoader(_swfLoaderArr[i]).loader != null)
						{
							SwfLoader(_swfLoaderArr[i]).closeAndRemoveLoader();
						}
					}
					catch(e:Error)
					{
						IO.traceError(e.errorID,e.message);
						IO.traceError(e.getStackTrace());
					}
					
					SwfLoader(_swfLoaderArr[i])._isLoading		=	false;
					SwfLoader.findFreeToLoad();//无完成回调
					IO.traceLog("SwfLoader关掉一个URL加载项(加载中)",url);
				}
			}
			//================
			//关闭完成
			
		}
		
		//寻找空闲的加载器加载队列
		private static function findFreeToLoad():void
		{
			var loadings		:SwfLoader;
			var freeLoadConut	:uint	=	0;
					
			var loadUrl : String = "";
			//寻找出一个加载器
			for(var i:int = 0 ; i < _lines ; i ++)
			{
				loadings	=	_swfLoaderArr[i]
				//找到空闲加载器
				if(!loadings._isLoading)
				{
					//如果找加载队列不为空时
					if(_itemArray1.length > 0)
					{
						//取出一个加载进行加载
						_isFree			=	false;
						var tArr:Array	=	_itemArray1.shift() as Array;					
						loadings.load(tArr[0],tArr[1],tArr[2],tArr[3]);						
					}
					else
					{
						freeLoadConut++;
					}
				}else
				{
					loadUrl += loadings._url + "  ;   ";
				}
			}
			
			IO.traceError("loadUrl = " + loadUrl,freeLoadConut,_lines);
			
			if(freeLoadConut == _lines && _isFree == false)
			{
				var tSize:uint	=	_itemArray2.length;
				
				_isFree			= 	true;
				_itemArray1		=	new Array();
				
				for(var j:int = 0 ; j < tSize ; j ++)
				{
					_itemArray1.push(_itemArray2.shift());
				}
				
				_itemArray2		=	new Array();
				
				findFreeToLoad();
			}
		}
		
		private function checkNeedEncrypt(url:String):Boolean
		{
			if( url.toLocaleLowerCase().indexOf("configdata.swf") != -1 )
			{
				isTest = false;
				return true;
			}
			return false;
			if( url.indexOf( "scene" ) != -1 ) return false;
			var arr:Array	=	url.split(".");
			var str:String	=	arr[arr.length-1];
			
			if(	str.toLocaleLowerCase()== "swf")
			{
				return true;
			}
			
			return false;	
		}


		//====================================
		
		private function agModelCompleteHandler(event:Event):void
		{
			freeUrlLoader();
			
			var tUrlLoader	:URLLoader 	= 	URLLoader(event.target);
			
			//获取二进制信息
			var data		:ByteArray	=	tUrlLoader.data;
			
			IO.traceLog("解密加载文件...",_url);
			
			//解码data
			if(_unEncryptByte == null)
			{
				IO.traceError("解密器设置失败！");
				agModelIoErrorHandler(null);
				return;
			}
			
			data		=	_unEncryptByte(data);
			
			IO.traceLog("解密加载完成。",_url);
			
			if(loader == null)
			{
				loader = new Loader();
				configureListeners(loader.contentLoaderInfo);
			}
			
			loader.loadBytes(data);
			
			urlLoader.data	=	null;
		}
		
		
		private function agModelIoErrorHandler(e:IOErrorEvent):void
		{
			if(_valList != null && _valList[0] is Function && _valList[0] != null)
			{
				_valList[0].call(this,e);
			}
			
			if(_complete != null)
			{
				_complete.call(this,null,_valList);
			}
			
			if(e != null)
			{
				IO.traceError("agModelIoErrorHandler->",e.text);
			}
			else
			{
				IO.traceError("agModelIoErrorHandler->cust null");
			}
			
			urlLoader.data	=	null;
			
			_isLoading		=	false;
			freeUrlLoader();
			SwfLoader.findFreeToLoad();
		}
		
		private function agModelProgressHandler(event:ProgressEvent):void
		{
			progressHandler(event);
		}
		
		/**
		 * 回收urlLoader
		 * 
		 * */
		private function freeUrlLoader():void
		{
			urlLoader.removeEventListener(Event.COMPLETE,agModelCompleteHandler);
			urlLoader.removeEventListener(IOErrorEvent.IO_ERROR,agModelIoErrorHandler);
			urlLoader.removeEventListener(ProgressEvent.PROGRESS,agModelProgressHandler);
		}
		
		
		/**
		 *获取版本号
		 * @param str
		 * @return 
		 * 
		 */
		private function getVersion():String
		{
			var v:String		=	model.mainIni.getContent("GameVersion","v");
			return v;
		}

		//=====================================
		private var intervalId :uint;
		private function load(
			url				:String,
			beAddContainer	:DisplayObjectContainer = 	null,
			complete		:Function				=	null,			
			valList			:Array					=	null):void
		{
			
			IO.traceLog("SWFLOADER加载资源,URL:",url," 当前内存：");
			
			_isLoading			=	true;
			_beAddContainer		=	beAddContainer;
			_complete			=	complete;
			_valList			=	valList;
			
			_url				=	CDN+url +"?v="+getVersion();
			
			request.url 		= 	_url;
			
//			if(_custLoadFunction != null && checkNeedEncrypt(url))
//			{
//				//调用外部加载方法进行加载
//				_cLoader	=	_custLoadFunction.call(this,
//					url,
//					custCompleteHandler,//加载完成回调【加载好的显示对象：DisplayObject】
//					progressHandler,//加载进度回调【进度事件：ProgressEvent】
//					custioErrorHandler//加载错误事件【错误事件：IOErrorEvent】
//				);
//			}
//			else 
			if(isTest && checkNeedEncrypt(url))
			{
				IO.traceLog("启用流加载",url);
				if(urlLoader == null)
					urlLoader = new URLLoader();
				
				urlLoader.dataFormat	=	URLLoaderDataFormat.BINARY;
				urlLoader.addEventListener(IOErrorEvent.IO_ERROR,agModelIoErrorHandler);
				urlLoader.addEventListener(ProgressEvent.PROGRESS,agModelProgressHandler);
				urlLoader.addEventListener(Event.COMPLETE,agModelCompleteHandler);
				urlLoader.load(request);
				_isLoading			=	true;
			}
			else
			{
				IO.traceLog("启用正常加载",url);
				//创建并记录loader
				
//				if(loader == null || 
//					(url.indexOf(".swf") != -1 && 
//						valList != null && 
//						valList.length == 4 && 
//						valList[3] == false))
//				{
//					//当资源需要特殊保存应用程序域时，保留loader,仅限.swf
//					//参看ResManager.loadResNoSave,ResManager.loadRes
//					loader	=	new Loader();
////					trace("11111111",url);
//				}
				if(loader == null)
				{
					loader = new Loader();
					configureListeners(loader.contentLoaderInfo)
				}
				
				
				try
				{
					var context	:LoaderContext;
					
					if (Security.sandboxType == Security.REMOTE && CDN != "")
					{
						request	=	new URLRequest(CDN+url+"?v="+getVersion());
						context	=	new LoaderContext(true,null,SecurityDomain.currentDomain);
					}
					else
					{
						request	=	new URLRequest(url+"?v="+getVersion());
						context	=	new LoaderContext(false,new ApplicationDomain());
					}
					
//					var context:LoaderContext	=	new LoaderContext();
//					context.checkPolicyFile		=	true;
//					context.applicationDomain	=	null;
//					context.securityDomain		=	SecurityDomain.currentDomain;
					
					loader.load(request,context);
					_isLoading			=	true;
					intervalId = setTimeout(removeloader,15000);
					function removeloader():void
					{
						try{
							if(_complete != null)
							{
								_complete.call(this,null,_valList);
							}
							closeAndRemoveLoader();
							removeTimer();
						}catch(e:Error)
						{
							IO.traceError("保护超时加载资源回调报错")
							closeAndRemoveLoader();
						}
						
					}
				}
				catch(e:Error)
				{
					IO.traceLog("LoadError:",e,e.getStackTrace());
					IO.traceLog("SecurityDomain.currentDomain",IO.toString(SecurityDomain.currentDomain));
					closeAndRemoveLoader();
				}
			}
		}
		
		public function removeTimer():void
		{
			clearTimeout(intervalId);
		}
		
		
		/**配置加载事件*/
		private function configureListeners(dispatcher:IEventDispatcher):void
        {
            dispatcher.addEventListener(Event.COMPLETE, 					completeHandler);
            dispatcher.addEventListener(ProgressEvent.PROGRESS,				progressHandler);
			dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR,	securityHandeler);
//            dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS,	httpStatusHandler);
//            dispatcher.addEventListener(Event.INIT,						initHandler);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR,				ioErrorHandler);
//            dispatcher.addEventListener(Event.OPEN,							openHandler);            
//            dispatcher.addEventListener(Event.UNLOAD,					unLoadHandler);
        }
		
		/**删除加载事件*/
		private function removeListeners(dispatcher:*):void
		{
			dispatcher.removeEventListener(HTTPStatusEvent.HTTP_STATUS			,httpStatusHandler);
			dispatcher.removeEventListener(ProgressEvent.PROGRESS				,progressHandler);
			dispatcher.removeEventListener(Event.COMPLETE						,completeHandler);
			dispatcher.removeEventListener(IOErrorEvent.IO_ERROR				,ioErrorHandler);
			dispatcher.removeEventListener(SecurityErrorEvent.SECURITY_ERROR	,securityHandeler);
//			dispatcher.removeEventListener(HTTPStatusEvent.HTTP_STATUS,	httpStatusHandler);
		}
		
		private function closeAndRemoveLoader():void
		{
			removeTimer();
			_isLoading		=	false;
			try
			{
				loader.unload()//(false);
			}
			catch(e:Error)
			{
//				trace("loader 尚未工作");
			}
			removeListeners(loader.contentLoaderInfo);
			loader = null;
			SwfLoader.findFreeToLoad();
		}
        
        private function completeHandler(event:Event):void
        {
			IO.traceLog("SWFLOADER加载资源完成！",_url);
			IO.traceError("test:",_url);
			var tContent:DisplayObject	=	event.target.content;
			try
			{
		
	        	if(_beAddContainer == null)
	        	{
					//回调完成
	        		if(_complete != null)
					{
		        		_complete.call(this,tContent,_valList);
						
		 			}
					//回调事件
					if(_valList != null && _valList[0] is Function && _valList[0] != null)
					{
						_valList[0].call(this,event);
					}
					
					
					closeAndRemoveLoader();
	        	}
	        	else
	        	{
					_beAddContainer.addChild(tContent);
	        		
					if(tContent.parent != null)
					{
						//如果已经添加成功
						//且有回调则回调
						if(_complete != null)
						{
							_complete.call(this,tContent,_valList);
						}        	
						_beAddContainer	=	null;
						
						//回调事件
						if(_valList != null && _valList[0] is Function && _valList[0] != null)
						{
							_valList[0].call(this,event);
						}
						
	//					closeAndRemoveLoader();
					}
					else
					{
						//否则监听加载成功的事件
						_beAddContainer.addEventListener(Event.ADDED,onObjBeAdd);
					}
					
					closeAndRemoveLoader();
	        	}
			}catch(e:Error)
			{
				IO.traceError("资源：",_url,"回调函数出错");
				closeAndRemoveLoader();
			}
		}
		
		/**
		 * 用自定义方法加载好的对象 
		 * @param val
		 * 
		 */		
		private function custCompleteHandler(val:DisplayObject,event:Event):void
		{
			IO.traceLog("SWFLOADER加载资源完成！",LoaderInfo(event.target).url," 当前内存：",System.totalMemory);
			
			//回调事件
			if(_valList != null && _valList[0] is Function && _valList[0] != null)
			{
				_valList[0].call(this,event);
			}
			
			if(_beAddContainer == null)
			{
				if(_complete != null)
				{
					_complete.call(this,val,_valList);
				}
				_isLoading		=	false;
				SwfLoader.findFreeToLoad();
			}
			else
			{
				_beAddContainer.addEventListener(Event.ADDED,onObjBeAdd);
				_beAddContainer.addChild(val);
			}
		}
        
        /**当加载对象被添加*/
        private function onObjBeAdd(e:Event):void
        {
        	e.currentTarget.removeEventListener(Event.ADDED,onObjBeAdd);
//        	this.dispatchEvent(new LoadEvent(LoadEvent.LOAD_ADD,e.target));
			if(_complete != null)
			{
				_complete.call(this,e.target,_valList);
			}        	
        	_beAddContainer	=	null;
			closeAndRemoveLoader();
        }
		
		private function securityHandeler(event:SecurityErrorEvent):void
		{
			
			try
			{
				if(_valList != null && _valList[0] is Function && _valList[0] != null)
				{
					_valList[0].call(this,event);
				}
				
				if(_complete != null)
				{
					_complete.call(this,null,_valList);
				}
				
				if(event != null)
				{
					IO.traceError("SwfLoadSercurityError->",event.text,_url);
				}
				else
				{
					IO.traceError("SwfLoadSercurityError->cust null",_url);
				}
				closeAndRemoveLoader();
			}catch(e:Error)
			{
				IO.traceError("资源：",_url,"回调函数出错");
				closeAndRemoveLoader();
			}
		}
        
        private function progressHandler(event:ProgressEvent):void
        {
			removeTimer();
			if(_valList != null && _valList[0] is Function && _valList[0] != null)
			{
				_valList[0].call(this,event);
			}
        }
        
        private function httpStatusHandler(event:HTTPStatusEvent):void
        {        	
//        	this.dispatchEvent(event);
            IO.traceLog("httpStatusHandler: " + event);
        }
        
        private function initHandler(event:Event):void
        {
//        	this.dispatchEvent(event);
			IO.traceLog("initHandler: " + event);
//			trace("[-2]");
        }
        
		private function ioErrorHandler(event:IOErrorEvent):void
		{
			try
			{
				if(_valList != null && _valList[0] is Function && _valList[0] != null)
				{
					_valList[0].call(this,event);
				}
				
				if(_complete != null)
				{
					_complete.call(this,null,_valList);
				}
				
				if(event != null)
				{
					IO.traceError("SwfLoadError->",event.text,_url);
				}
				else
				{
					IO.traceError("SwfLoadError->cust null",_url);
				}
				closeAndRemoveLoader();
			}catch(e:Error)
			{
				IO.traceError("资源：",_url,"回调函数出错");
				closeAndRemoveLoader();
			}
		}
		
		private function custioErrorHandler(event:IOErrorEvent):void
		{
			if(_valList != null && _valList[0] is Function && _valList[0] != null)
			{
				_valList[0].call(this,event);
			}
			
			if(_complete != null)
			{
				_complete.call(this,null,_valList);
			}
			
			if(event != null)
			{
				IO.traceError("SwfLoadError->",event.text,_url);
			}
			else
			{
				IO.traceError("SwfLoadError->cust null",_url);
			}
			closeAndRemoveLoader();
		}
        
        private function openHandler(event:Event):void
        {
//        	this.dispatchEvent(event.clone());
			IO.traceLog("openHandler: " + event);
        }
        
//        private function unLoadHandler(event:Event):void
//        {
////        	this.dispatchEvent(event.clone());
//			IO.traceLog("unLoadHandler: " + event);
//			
//			closeAndRemoveLoader()
//			
//			SwfLoader._testCount--;
//			_isLoading	=	false;
//			SwfLoader.findFreeToLoad();
//        }
	}
}